public without sharing class OORDuplicateCheck{
        
       //static var to prevent recursive trigger updates
       //validating a change in dev salesforce! 
        private static boolean IsRecursive = false;
        public static boolean IsRecursive() {     
           return isRecursive;
        }        
         public static void setRecursive(boolean value) {     
           isRecursive=value;
        }
        
        public static ID LocalAdsLeadRecordType;// = RecordTypeHelper.GetRecordTypeID('Lead', 'Local Advertiser');
        public static ID LocalAdsAccountRecordType;// = RecordTypeHelper.GetRecordTypeID('Account', 'Local OOR Customer');
        
       public static ID GetLocalAdsLeadRecordType() {
            //Initialize all RT if calling for first time           
            if( LocalAdsLeadRecordType == null ) 
                   GetRecordTypes();
                            
          return LocalAdsLeadRecordType;
            
        }
        //retrieve the record types for lead and account for customer care
        public static void  GetRecordTypes()
        {     
            if(LocalAdsLeadRecordType == null || LocalAdsAccountRecordType == null )
            {
                RecordTypeHelper.PrepareToLoad('Lead');                             
                RecordTypeHelper.PrepareToLoad('Account');                              
                LocalAdsLeadRecordType = RecordTypeHelper.GetRecordTypeID('Lead', 'Local Advertiser');
                LocalAdsAccountRecordType = RecordTypeHelper.GetRecordTypeID('Account', 'Local OOR Customer');            
            }
        }


        public static void MoveStandardAddress(List<Lead> leads, Map<ID, Lead> oldLeads, boolean IsInsert)
        {       
            if(IsInsert)    {
               for (Lead lead : leads) {
                    System.debug('*****Venkat***lead.RecordTypeid == LocalAdsLeadRecordType && lead.LeadSource == ****'+lead.RecordTypeid+'*****'+LocalAdsLeadRecordType+'****lead.LeadSource*****'+lead.LeadSource);
                     if (lead.RecordTypeid == LocalAdsLeadRecordType && lead.LeadSource == 'Salesgenie.com'){
                     System.debug('*****Venkat***lead.');
                        if(lead.Street !=null ) lead.Business_Address_L1__c = lead.Street;
                        if(lead.City != null) lead.City__c = lead.City;
                        if(lead.State != null) lead.State_Province__c = lead.State;                            
                        if(lead.PostalCode != null) lead.Zip_Postal_Code__c= lead.PostalCode;                                                
                     }//if                   
               }//for
            }//if           
        }
                
        //throw error if an account with same phone is found!       
        public static void DeDupeAccountPhone(List<Lead> leads, Map<ID, Lead> oldLeads, boolean IsInsert)
        {
           Map<String, Lead> leadPhoneDupeMap = new Map<String, Lead>();
           Map<String, Lead> ContactPrimPhoneDupeMap = new Map<String, Lead>();
           string strid;
           for (Lead lead : leads) {
            if (lead.RecordTypeid == LocalAdsLeadRecordType){
              string CleanLeadPhone =  SilCustomerHelper.CreatePhoneNumberHash(lead.Phone);
              if((!IsInsert)&& (lead.Company != oldLeads.get(lead.Id).Company|| lead.City != oldLeads.get(lead.Id).City || lead.State != oldLeads.get(lead.Id).State  ||  CleanLeadPhone!= oldLeads.get(lead.Id).cleanphonetext__c)){
                       lead.duplicate__c = false;
                       lead.IsDupe__C = false;
                       lead.Duplicate_Owner__c = null;
                       lead.DupingAccountID__c =null;
                       lead.DupingLeadID__c =null;
                       lead.Master__c=true;
                       strid = lead.id;
                       lead.Unique_lead_list__c = lead.id; } 
     /**         if((!IsInsert)&&(lead.Company != oldLeads.get(lead.Id).Company || lead.City != oldLeads.get(lead.Id).City || lead.State != oldLeads.get(lead.Id).State)){
                       lead.duplicate__c = false;
                       lead.IsDupe__C = false;
                       lead.Duplicate_Owner__c = null;
                       lead.DupingAccountID__c =null;
                       lead.Master__c=true; 

              } **/
              // 1. Build the map of phone changes  
              if (lead.RecordTypeid == LocalAdsLeadRecordType && lead.Phone != null && CleanLeadPhone != null && 
                        (IsInsert ||  CleanLeadPhone != oldLeads.get(lead.Id).CleanPhoneText__c ) ) {    
                  leadPhoneDupeMap.put(CleanLeadPhone, lead);
                 ContactPrimPhoneDupeMap.put(CleanLeadPhone,Lead);
                 
            }
            
          }
        }
         if(leadPhoneDupeMap.size() > 0  ){             
               OORDuplicateCheck.FindExistingAccountsPhone(leadPhoneDupeMap,ContactPrimPhoneDupeMap);
         }
           
        } 
             
        // find all the leads in
        // the database having the same Phone number as any
        // of the leads being inserted or updated.  
        private static void FindExistingAccountsPhone(Map<String, Lead> leadPhoneDupeMap,Map<String, Lead> ContactPrimPhoneDupeMap)
        {                               
            for (Account account : [SELECT Phone, CleanPhoneText__c FROM Account WHERE CleanPhoneText__c IN :leadPhoneDupeMap.KeySet() and RecordTypeid = :LocalAdsAccountRecordType and ((Account_status__c = 'Active' OR Account_status__c = 'Prospect' ) and Account_status__c!=null)]) {
                 Lead newLead = leadPhoneDupeMap.get(account.CleanPhoneText__c);
                 newLead.Phone.addError('An account with this Phone Number already exists.');
            
            }
            for (Account account : [SELECT Phone,CleanPrimaryPhone_text__c,CleanPhoneText__c, Primary_Phone__C FROM Account WHERE CleanPrimaryPhone_text__c IN :ContactPrimPhoneDupeMap.KeySet() and RecordTypeid = :LocalAdsAccountRecordType and ((Account_status__c = 'Active' OR Account_status__c = 'Prospect') and Account_status__c!=null)]) {
                 Lead newLead = ContactPrimPhoneDupeMap.get(account.CleanPrimaryPhone_text__c);
                 newLead.Phone.addError('A Primary Contact with this Phone Number already exists.');
            }
        }
        //called after insert ,update of leads
        //the reason why we are doing this in after trigger is that Id of lead object is not available in the before triggger
        public static void DeDupeLeadAccount(Map<ID,Lead> leads, Map<ID,Lead> oldLeads ,boolean IsInsert)
        {               
             Set<ID> bizNameLeads = new Set<ID>();
             Set<ID>  phoneNumLeads = new Set<ID>();
             set<string> bizaccNames = new Set<string>();
             Set<string> bizNames = new Set<string>();
             Set<string> oldbizNames = new Set<string>();
             Set<string>  phones= new Set<string>(); 
             Set<string>  oldphones= new Set<string>(); 
                             
             //get the newly inserted leads..
             //List<Lead> triggerRecords = [select id,DupingLeadID__c,IsDupe__C,Company, Phone,RecordTypeid,Duplicate_Status__c from lead where id IN :leads.keySet() and RecordTypeid = :LocalAdsLeadRecordType ];
                   
             for (Lead lead : leads.values()){              
               //store phone numbers..
               if (lead.cleanphonetext__c!= null && (IsInsert || (lead.cleanphonetext__c!= oldLeads.get(lead.Id).cleanphonetext__c  || lead.Company != oldLeads.get(lead.Id).Company)))   {                                                 
                       phoneNumLeads.add(lead.Id);                       
                       phones.add(lead.cleanphonetext__c);
                       If(!ISINSERT &&(lead.cleanphonetext__c!= oldLeads.get(lead.Id).cleanphonetext__c)){
                           oldphones.add(oldLeads.get(lead.Id).cleanphonetext__c); 
                       }                                                           
               }
               
               if (lead.Company != null && (IsInsert || (lead.Company != oldLeads.get(lead.Id).Company || lead.City != oldLeads.get(lead.Id).City || lead.State != oldLeads.get(lead.Id).State || lead.cleanphonetext__c!= oldLeads.get(lead.Id).cleanphonetext__c)))   {                                                  
                       bizNameLeads.add(lead.Id); 
                       bizNames.add(lead.Company.toLowerCase());
                       If(!IsInsert && (lead.Company != oldLeads.get(lead.Id).Company)){
                           oldbizNames.add(oldLeads.get(lead.Id).Company.toLowerCase());
                       }                      
                       bizaccNames.add(lead.Company+lead.City+lead.State);                             
               }
             }
                
                //check existing leads/account in db if any company matches
                if(bizNameLeads.size() > 0 || phoneNumLeads.size() > 0  )   {
                       UpdateLeads.doUpdate(bizNameLeads, bizNames, phoneNumLeads, phones, LocalAdsLeadRecordType,LocalAdsAccountRecordType,bizaccNames,oldphones,oldbizNames);                               
                }
        }
        
 // check test method  
 
     static testmethod void testOORDuplicateCheck()
     {
        OORDuplicateCheck newobj = new OORDuplicateCheck();
        List<Lead> ld = new List<Lead>();
        Map<Id,Lead> mapld= new Map<Id,Lead>();
        Map<String,Lead> mapStrgld= new Map<String,Lead>();
        boolean isinsert=true;

        ID localLeadRecID= RecordTypeHelper.GetRecordTypeID('Lead', 'Local Advertiser');

        // creating the list of leads 

        // record 1
        try
        {
        Lead ld1 = new Lead();

        List<Lead> ldlist = new List<Lead>();
        List<Lead> ldlist2 = new List<Lead>();

        //record 1
        ld1.RecordTypeId=localLeadRecID;
        ld1.Company ='Test OOR 5';
        ld1.FirstName='John5';
        ld1.LastName='Smith5';
        ld1.Phone='89898933333';
        ld1.Disposition__c='No Sale';
        ld1.Most_Recent_Note__c='test3';
        ld1.LeadSource = 'Salesgenie.com';  
        ld1.Street = 'jind';
        ld1.City ='ddd';
        ld1.State ='dddd';
        ld1.PostalCode = '56764747';
        ldlist.add(ld1);

        //record 2
        Lead ld2 = new Lead();

        ld2.RecordTypeId=localLeadRecID;
        ld2.Company ='Test OOR 6';
        ld2.FirstName='John6';
        ld2.LastName='Smith6';
        ld2.Phone='898989666666';
        ld2.Disposition__c='No Sale';
        ld2.Most_Recent_Note__c='test3';
        ld1.LeadSource = 'Salesgenie.com';
        ldlist.add(ld2);


        Test.startTest();
        insert ldlist;
        Test.stopTest();
        
        Map<ID, Lead> savedLead = new Map<ID, Lead>([SELECT Id from Lead where ID in :ldlist]);
        ldlist[0].Company = 'Test OOR 7';
        update ldlist;
        Map<String, Lead> savedStrgLead = new Map<String, Lead>([SELECT Id from Lead where ID in :ldlist]);
        system.debug('****savedStrgLead***'+savedStrgLead);


        IsRecursive();
        setRecursive(true);
        MoveStandardAddress(ldlist,savedLead,isinsert);
        DeDupeAccountPhone(ldlist,savedLead,isinsert);
        DeDupeAccountPhone(ldlist,savedLead,false);
        FindExistingAccountsPhone(savedStrgLead,savedStrgLead );
        DeDupeLeadAccount(savedLead,savedLead,isinsert); 

        }
        catch(Exception e){
        System.debug('*** exception Catch'+e);
        }



    }  
 
      
}